package org.jeecg.modules.tencent.handle;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.jiguang.common.DeviceType;
import cn.jpush.api.push.model.PushPayload;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.modules.doctor.entity.Doctor;
import org.jeecg.common.modules.doctor.entity.DoctorWxUserinfoRelation;
import org.jeecg.common.modules.doctor.service.IDoctorService;
import org.jeecg.common.modules.doctor.service.IDoctorWxUserinfoRelationService;
import org.jeecg.common.modules.group.entity.ChatRecord;
import org.jeecg.common.modules.group.service.IChatRecordService;
import org.jeecg.common.modules.im.ImService;
import org.jeecg.common.modules.order.entity.OrderInfo;
import org.jeecg.common.modules.order.service.IOrderInfoService;
import org.jeecg.common.modules.wx.entity.WxUserinfo;
import org.jeecg.common.modules.wx.service.IWxUserinfoService;
import org.jeecg.common.util.IMJsonUtil;
import org.jeecg.common.util.enums.OrderStatusEnum;
import org.jeecg.common.util.enums.centent.ChatMsgEnum;
import org.jeecg.common.util.oss.OssBootUtil;
import org.jeecg.common.util.push.JPushUtils;
import org.jeecg.common.util.tencent.request.ChatMsgRequest;
import org.jeecg.common.util.tencent.response.IMBaseResponse;
import org.jeecg.common.util.tencent.response.UserStatusResponse;
import org.jeecg.modules.abs.TencentCallBackAbstract;
import org.jeecg.modules.service.wx.WeixinService;
import org.jeecg.modules.tencent.enums.IMCallbackEnum;
import org.jeecg.modules.tencent.vo.GroupMsgPreVo;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.jeecg.modules.tencent.util.TencentCallBackConstants.GROUP_MSG_AFTER;

/**
 * @author guoyh
 * @ClassName GroupMsgPreHandle
 * @Description
 * @since 2020/8/28 23:55
 **/
@Component(value = GROUP_MSG_AFTER)
@Slf4j
public class GroupMsgAfterHandle extends TencentCallBackAbstract {

    @Resource
    private IChatRecordService chatRecordService;

    @Resource
    private IDoctorWxUserinfoRelationService doctorWxUserinfoRelationService;

    @Resource
    private IOrderInfoService orderInfoService;

    @Resource
    private IWxUserinfoService wxUserinfoService;
    @Resource
    private WeixinService weixinService;
    @Resource
    private JPushUtils jPushUtils;
    @Resource
    private ImService imService;
    @Resource
    private IDoctorService doctorService;


    @Override
    public IMCallbackEnum getHandleClass() {
        return IMCallbackEnum.GROUP_MSG_AFTER;
    }

    @Override
    protected IMBaseResponse handle(String body) {
        GroupMsgPreVo groupMsgPreVo = IMJsonUtil.parse(body,GroupMsgPreVo.class);
        if (Objects.isNull(groupMsgPreVo)){
            log.error("转换消息Bean失败{}",body);
            return IMBaseResponse.buildFail("转换消息Bean失败");
        }
        //保存聊天记录
        saveChatRecord(groupMsgPreVo,body);
        DoctorWxUserinfoRelation relation = doctorWxUserinfoRelationService.getByGroupId(groupMsgPreVo.getGroupId());
        if (Objects.isNull(relation)){
            return IMBaseResponse.buildFail("获取医患关系失败");
        }
        //激活订单
        activeOrder(relation,body);
        //发送自定义消息
        sendCustomMsg(relation,groupMsgPreVo);
        //推送极光
        sendJPush(relation,groupMsgPreVo);
        return IMBaseResponse.buildSuccess();
    }

    private void sendJPush(DoctorWxUserinfoRelation relation,GroupMsgPreVo groupMsgPreVo){
        WxUserinfo wxUserinfo = wxUserinfoService.getByOpenid(relation.getOpenid());
        if (StringUtils.equals(wxUserinfo.getId(),groupMsgPreVo.getFromAccount())){
            String groupName = wxUserinfo.getNickname();
            String groupId = groupMsgPreVo.getGroupId();
            Doctor doctor = doctorService.getById(relation.getDoctorId());
            if (Objects.isNull(doctor) || Objects.isNull(doctor.getDeviceType()) || StringUtils.isBlank(doctor.getDeviceToken())){
                log.warn("未获取到医生信息或医生设备信息为空,医生ID：{},消息：{}",relation.getDoctorId(),JSONUtil.toJsonStr(groupMsgPreVo));
                return;
            }
            UserStatusResponse userStatusResponse = imService.getUserState(doctor.getId());
            if (Objects.isNull(userStatusResponse) ||
                    CollectionUtils.isEmpty(userStatusResponse.getQueryResult()) ||
                    StringUtils.equals(userStatusResponse.getQueryResult().get(0).getStatus(),"Online")){
                log.warn("未获取到状态或用户状态为在线,用户ID：{}，消息：{}",relation.getDoctorId(),JSONUtil.toJsonStr(groupMsgPreVo));
                return;
            }
            Map<String,String> map = Maps.newHashMap();
            map.put("type","chat");
            map.put("chatId",groupId);
            map.put("chatName",groupName);
            PushPayload payload = jPushUtils.buildPayload(Lists.newArrayList(doctor.getDeviceToken()),Objects.equals(doctor.getDeviceType(), 1) ? DeviceType.Android : DeviceType.IOS,"您有一条新消息","大医智慧",map);
            jPushUtils.sendRequest(payload);
        }
    }

    /**
     * 发送自定义消息
     * @param relation
     * @param groupMsgPreVo
     */
    private void sendCustomMsg(DoctorWxUserinfoRelation relation,GroupMsgPreVo groupMsgPreVo){
        try {
            WxUserinfo wxUserinfo = wxUserinfoService.getByOpenid(relation.getOpenid());
            if (Objects.nonNull(wxUserinfo) && !StringUtils.equals(wxUserinfo.getId(),groupMsgPreVo.getFromAccount()) && compareTime(wxUserinfo.getLastConnTime())){
                List<ChatMsgRequest.ChatMsgBody> msgBodys = groupMsgPreVo.getMsgBody();
                if (CollectionUtils.isNotEmpty(msgBodys)){
                    ChatMsgRequest.ChatMsgBody chatMsgBody = msgBodys.get(0);
                    ChatMsgEnum chatMsgEnum = ChatMsgEnum.valueOf(chatMsgBody.getMsgType());
                    if (Objects.isNull(chatMsgEnum)){
                        log.error("未知的消息类型{}",chatMsgBody.getMsgType());
                    }else{
                        String content = null;
                        switch (chatMsgEnum){
                            case TIMCustomElem:
                                log.info("自定义消息，不处理");
                                break;
                            case TIMTextElem:
                                content = chatMsgBody.getMsgContent().getText();
                                break;
                            default:
                                content = chatMsgEnum.getDesc();
                                break;
                        }
                        if (StringUtils.isNotBlank(content)){
                            weixinService.sendCustomerMessage(groupMsgPreVo.getGroupId(),content);
                        }
                    }
                }else{
                    log.error("消息内容为空");
                }
            }else{
                log.error("未获取到患者或此消息是患者发送的:发送者id：{},患者ID：{}",groupMsgPreVo.getFromAccount(),Objects.nonNull(wxUserinfo) ? wxUserinfo.getId() : null);
            }
        } catch (Exception e) {
            log.error("消息回调，通知患者异常{}",e);
        }
    }

    /**
     * 激活订单
     * @param relation
     * @param body
     */
    private void activeOrder(DoctorWxUserinfoRelation relation,String body){
        try {
            WxUserinfo wxUserinfo = wxUserinfoService.getByOpenid(relation.getOpenid());
            LambdaQueryWrapper<OrderInfo> query = Wrappers.lambdaQuery();
            query.eq(OrderInfo::getDoctorId,relation.getDoctorId());
            query.eq(OrderInfo::getWxUserinfoId,wxUserinfo.getId());
            query.eq(OrderInfo::getActive,false);
            query.eq(OrderInfo::getStatus, OrderStatusEnum.DOING.getCode());
            List<OrderInfo> orderInfos = orderInfoService.list(query);
            if (CollectionUtils.isNotEmpty(orderInfos)){
                orderInfos.stream().forEach(item -> {
                    item.setActive(true);
                    orderInfoService.updateById(item);
                });
            }
        } catch (Exception e) {
            log.error("激活医生订单失败{}",body);
        }
    }

    /**
     * 保存聊天记录
     * @param groupMsgPreVo
     * @param body
     */
    private void saveChatRecord(GroupMsgPreVo groupMsgPreVo,String body){
        try {
            ChatRecord chatRecord = new ChatRecord();
            chatRecord.setFromId(groupMsgPreVo.getFromAccount());
            chatRecord.setGroupId(groupMsgPreVo.getGroupId());
            chatRecord.setSenderId(groupMsgPreVo.getOperatorAccount());
            chatRecord.setMsg(body);
            chatRecord.setCreateTime(new Date());
            String ossUrl = buildOssFile(groupMsgPreVo);
            chatRecord.setOssFilePath(ossUrl);
            chatRecordService.save(chatRecord);
        } catch (Exception e) {
            log.error("保存消息记录失败{}",body);
        }
    }

    private boolean compareTime(Date lastConnTime){
        if (Objects.isNull(lastConnTime)){
            return true;
        }
        Date now = new Date();
        if (Math.subtractExact(now.getTime(),lastConnTime.getTime()) >  30000L){
            return true;
        }
        return false;
    }

    private String buildOssFile(GroupMsgPreVo groupMsgPreVo){
        if (CollectionUtils.isEmpty(groupMsgPreVo.getMsgBody())){
            return null;
        }
        ChatMsgRequest.ChatMsgBody msgBody = groupMsgPreVo.getMsgBody().get(0);
        if (!StringUtils.equals(msgBody.getMsgType(),ChatMsgEnum.TIMImageElem.name())){
            return null;
        }
        try {
            String suffix = getSuffix(msgBody.getMsgContent().getImageFormat());
            Map<String,String> map = Maps.newHashMap();
            String uuid = IdUtil.fastSimpleUUID();
            msgBody.getMsgContent().getImageInfoArray().stream().forEach(item -> {
                try {
                    String url = item.getUrl();
                    InputStream inputStream = new URL(url).openStream();
                    String type = getType(item.getType());
                    String path = getPath(groupMsgPreVo.getGroupId(),groupMsgPreVo.getFromAccount(),uuid,type,suffix);
                    String ossUrl = OssBootUtil.upload(inputStream,path);
                    map.put(type,ossUrl);
                } catch (IOException e) {
                    log.error("获取远程图片失败{}",item.getUrl());
                }
            });
            return JSONUtil.toJsonStr(map);
        } catch (Exception e) {
            log.error("上传图片失败{}",JSONUtil.toJsonStr(groupMsgPreVo),e);
            return null;
        }
    }

    private String getPath(String groupId,String senderId,String msgId,String type,String suffix){
        return StrUtil.format("chatrecord/{}/{}_{}_{}{}",groupId,senderId,msgId,type,suffix);
    }

    private String getType(Integer type){
        switch (type){
            case 1:
                return "original";
            case 2:
                return "large";
            default:
                return "small";
        }
    }

    private String getSuffix(Integer imageFormat){
        switch (imageFormat){
            case 2:
                return ".gif";
            case 3:
                return ".png";
            case 4:
                return ".bmp";
            default:
                return ".jpg";
        }
    }
}
